using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Drawing;

namespace ImageProvider
{
    public abstract class ImageProviderBase : ProviderBase
    {
        // Properties
        public virtual string ApplicationName { get; set; }

        //public abstract bool CanSaveImages { get; set; }

        // Methods
        public abstract Image RetrieveImage(string name, ImageCatalogue catalogue = null);

        public abstract IEnumerable<ImageCatalogue> RetrieveCatalogues(ImageCatalogue catalogue = null);

        public abstract void SaveImage(string name, Image image, ImageCatalogue catalogue = null);

        public abstract ImageCatalogue AddCatalogue(string name, ImageCatalogue parent = null);

        public override void Initialize(string name, NameValueCollection config)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            if (string.IsNullOrEmpty(name))
            {
                name = this.GetType().Name;
            }

            base.Initialize(name, config);

            // Initialize applicationName
            this.ApplicationName = this.GetValue<string>(config, "applicationName", x => string.IsNullOrEmpty(x) ? "/" : null);
        }

        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config">The config.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="setUp">The set up.</param>
        /// <returns></returns>
        protected T GetValue<T>(NameValueCollection config, string propertyName, Func<string, string> setUp = null)
        {
            var value = config[propertyName];
            config.Remove(propertyName);
            value = setUp != null ? setUp(value) : value;
            var result = (T)Convert.ChangeType(value, typeof(T));
            return result;
        }

        /// <summary>
        /// Checks for extra attributes. Throws an exception if unrecognized attributes remain
        /// </summary>
        /// <param name="config">The config.</param>
        /// <exception cref="System.Configuration.Provider.ProviderException">Unrecognized attribute:  + attr</exception>
        protected void CheckForExtraAttributes(NameValueCollection config)
        {
            if (config.Count > 0)
            {
                var attr = config.GetKey(0);
                if (!String.IsNullOrEmpty(attr))
                {
                    throw new ProviderException("Unrecognized attribute: " + attr);
                }
            }
        }
    }
}